package com.zhitxx.progress_webview

import android.animation.*
import android.content.Context
import android.graphics.Canvas
import android.graphics.Color
import android.graphics.Paint
import android.util.AttributeSet
import android.view.View
import android.view.animation.DecelerateInterpolator
import android.view.animation.LinearInterpolator
import android.widget.FrameLayout
import androidx.annotation.ColorInt
import androidx.annotation.ColorRes
import androidx.core.view.isVisible


class WebProgressBar : FrameLayout, ProgressSpec {
    private var color: Int = 0 //进度条的yanse
        set(value) {
            mPaint.color = value
            field = value
        }
    private var mPaint: Paint = Paint() //画笔
    private var animations: Animator? = null//进度条动画
    private var weightWidth: Int = 0
    val maxUnformSpeedDuration: Int = 5 * 1000 //默认匀速动画时长
    val maxDecelerateSpeedDuration: Int = 600 //默认加速后减速动画最大时长
    val doEndAnimationDuration: Int = 300 //结束动画时长
    var currentMaxUnformSpeedDuration: Int = maxUnformSpeedDuration //当前匀速动画最大的时长
    var currentMaxDecelerateSpeedDuration: Int = maxDecelerateSpeedDuration // 当前加速后减速动画最大时长
    var tag = 0 //当前标记tag
    val unStart: Int = 0
    val started: Int = 1
    val finished: Int = 2
    var currentProgress: Float = 0f

    //默认的高度
    var webProgressDefaultHeight = 3


    constructor(context: Context) : this(context, null)

    constructor(context: Context, attrs: AttributeSet?) : this(context, attrs, 0)

    constructor(context: Context, attrs: AttributeSet?, defStyleAttr: Int) : super(
        context,
        attrs,
        defStyleAttr
    ) {

        init(context, attrs, defStyleAttr)
    }

    private fun init(context: Context, attrs: AttributeSet?, defStyleAttr: Int) {
        color = Color.parseColor("#c15d3e")
        mPaint.isAntiAlias = true
        mPaint.color = color
        mPaint.strokeCap = Paint.Cap.SQUARE

        weightWidth = context.resources.displayMetrics.widthPixels
//        webProgressDefaultHeight = dipToPx(context, 5f)
    }


    /**
     *设置进度条的高度
     */
    fun setWebProgressDefaultHeights(height: Float) {
        this.webProgressDefaultHeight = dipToPx(context, height)
    }

    fun setColors(color: String) {
        this.color = Color.parseColor(color)
        mPaint.color = this.color
    }

    fun setColors(@ColorInt color: Int) {
        this.color = color
        mPaint.color = this.color
    }

    fun setColors(@ColorRes colorId: Int, isColorRes: Boolean) {
        this.color = context.resources.getColor(colorId)
        mPaint.color = this.color
    }

    //measure  start
    override fun onMeasure(widthMeasureSpec: Int, heightMeasureSpec: Int) {
        var wMode = MeasureSpec.getMode(widthMeasureSpec)
        var width = MeasureSpec.getSize(widthMeasureSpec)
        var hMode = MeasureSpec.getMode(heightMeasureSpec)
        var height = MeasureSpec.getSize(heightMeasureSpec)
        if (wMode == MeasureSpec.AT_MOST) {
            width = if (width <= context.resources.displayMetrics.widthPixels) {
                width
            } else {
                context.resources.displayMetrics.widthPixels
            }
        }
        if (hMode == MeasureSpec.AT_MOST) {
            height = webProgressDefaultHeight
        }
        this.setMeasuredDimension(width, height)
    }
    //measure end

    override fun dispatchDraw(canvas: Canvas?) {
        canvas!!.drawRect(
            0f,
            0f,
            currentProgress / 100 * this.width.toFloat(),
            this.height.toFloat(),
            mPaint
        )
    }

    //大小状态改变的处理逻辑
    override fun onSizeChanged(w: Int, h: Int, oldw: Int, oldh: Int) {
        super.onSizeChanged(w, h, oldw, oldh)
        this.weightWidth = measuredWidth
        var screenWidth = context.resources.displayMetrics.widthPixels
        if (weightWidth >= screenWidth) {
            currentMaxDecelerateSpeedDuration = maxDecelerateSpeedDuration
            currentMaxUnformSpeedDuration = maxUnformSpeedDuration
        } else {
            var rate = (this.weightWidth / screenWidth).toFloat()
            currentMaxDecelerateSpeedDuration = (maxDecelerateSpeedDuration * rate).toInt()
            currentMaxUnformSpeedDuration = (maxUnformSpeedDuration * rate).toInt()
        }

    }

    private var target = 0f

    //执行动画
    fun startAnim(isFinish: Boolean) {
        val v: Float = if (isFinish) {
            100f
        } else {
            95f
        }

        if (animations != null && animations!!.isStarted) {
            animations!!.cancel()
        }
        currentProgress = if (currentProgress == 0f) {
            0.00000001f
        } else {
            currentProgress
        }
        if (!isFinish) {
            var valueAnim: ValueAnimator = ValueAnimator.ofFloat(currentProgress, v)
            var residue = 1f - currentProgress / 100 - 0.05f
            valueAnim.interpolator = LinearInterpolator()
            valueAnim.setDuration((residue * currentMaxUnformSpeedDuration).toLong())
            valueAnim.addUpdateListener(mAnimatorUpdateListener)
            valueAnim.start()
            this.animations = valueAnim
        } else {


            var segment95Animator: ValueAnimator? = null
            if (currentProgress < 95f) {
                segment95Animator = ValueAnimator.ofFloat(currentProgress, 95f)
                val residue = 1f - currentProgress / 100f - 0.05f
                segment95Animator.interpolator = LinearInterpolator()
                segment95Animator.duration =
                    (residue * currentMaxDecelerateSpeedDuration) as Long
                segment95Animator.interpolator = DecelerateInterpolator()
                segment95Animator.addUpdateListener(mAnimatorUpdateListener)
            }
            val mObjectAnimator = ObjectAnimator.ofFloat(this, "alpha", 1f, 0f)
            mObjectAnimator.duration = doEndAnimationDuration.toLong()
            val mValueAnimatorEnd = ValueAnimator.ofFloat(95f, 100f)
            mValueAnimatorEnd.duration = doEndAnimationDuration.toLong()
            mValueAnimatorEnd.addUpdateListener(mAnimatorUpdateListener)

            var mAnimatorSet = AnimatorSet()
            mAnimatorSet.playTogether(mObjectAnimator, mValueAnimatorEnd)

            if (segment95Animator != null) {
                val mAnimatorSet1 = AnimatorSet()
                mAnimatorSet1.play(mAnimatorSet).after(segment95Animator)
                mAnimatorSet = mAnimatorSet1
            }
            mAnimatorSet.addListener(mAnimatorListenerAdapter)
            mAnimatorSet.start()
            animations = mAnimatorSet
        }
        tag = started
        target = v
    }

    var mAnimatorUpdateListener: ValueAnimator.AnimatorUpdateListener =
        ValueAnimator.AnimatorUpdateListener { animation ->
            val t = animation!!.animatedValue as Float
            currentProgress = t
            this@WebProgressBar.invalidate()
        }

    var mAnimatorListenerAdapter: AnimatorListenerAdapter = object : AnimatorListenerAdapter() {
        override fun onAnimationEnd(animation: Animator?) {
            doEnd()
        }
    }

    private fun doEnd() {
        if (tag == finished && currentProgress == 100f) {
            visibility = View.GONE
            currentProgress = 0f
            this.alpha = 1f
        }
        tag = unStart
    }


    override fun onDetachedFromWindow() {
        super.onDetachedFromWindow()
        if (animations != null && animations!!.isStarted) {
            animations!!.cancel()
        }
    }

    override fun show() {
        if (visibility == View.GONE) {
            this.visibility = View.VISIBLE
            currentProgress = 0f
            startAnim(false)
        }
    }

    override fun hide() {
        tag = finished
    }

    override fun reset() {
        currentProgress = 0f
        if (animations != null && animations!!.isStarted) {
            animations!!.cancel()
        }
    }


    fun setProgress(newProgress: Float) {
        if (visibility == View.GONE) {
            visibility = View.VISIBLE
        }
        if (currentProgress < 95) {
            return
        }
        if (tag == finished) {
            startAnim(true)
        }
    }

    override fun setProgress(newProgress: Int) {
        setProgress(newProgress.toFloat())
    }

    fun dipToPx(context: Context, dpValue: Float): Int {
        val scale = context.resources.displayMetrics.density
        return (dpValue * scale + 0.5f).toInt()
    }

}